/************************************************************************
Copyright (c) 2010, 2013, C.R. All rights reserved. 

E-mail: crtoyou@gmail.com; crtoyou@163.com

You can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation version 3 of the License.

This source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. if not, write to the Free Software Foundation, Inc., 
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
************************************************************************/

#ifndef __CR_SYMBOL_H__
#define __CR_SYMBOL_H__

#include <functional>
#include <tchar.h>
#include <crdebug.h>

namespace cr {

template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct symbol
{
	TCHAR str[MAX_LEN];
	symbol(const TCHAR* s = _T("")) { ASSERT(s); _tcsncpy_s(str, MAX_LEN, s, MAX_LEN-1); } 
	inline void operator = (const TCHAR* s) { ASSERT(s); _tcsncpy_s(str, MAX_LEN, s, MAX_LEN-1); }
	inline void length() { return _tcslen(str); }
	inline bool empty() { return !!str[0]; }
	inline void clear() { str[0] = NULL; }
};

// TEMPLATE STRUCT equal_to
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct equal_to_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator==
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) == 0 
			: _tcsicmp(_Left.str, _Right.str) == 0;
	}
};

// TEMPLATE STRUCT not_equal_to
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct not_equal_to_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator!=
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) != 0 
			: _tcsicmp(_Left.str, _Right.str) != 0;
	}
};

// TEMPLATE STRUCT greater
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct greater_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator>
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) > 0 
			: _tcsicmp(_Left.str, _Right.str) > 0;
	}
};

// TEMPLATE STRUCT less
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct less_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator<
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) < 0 
			: _tcsicmp(_Left.str, _Right.str) < 0;
	}
};

// TEMPLATE STRUCT greater_equal
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct greater_equal_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator>=
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) >= 0 
			: _tcsicmp(_Left.str, _Right.str) >= 0;
	}
};

// TEMPLATE STRUCT less_equal
template <unsigned short MAX_LEN, bool SENSITIVE = true>
struct less_equal_symbol
	: public std::binary_function<symbol<MAX_LEN, SENSITIVE>, symbol<MAX_LEN, SENSITIVE>, bool>
{	// functor for operator<=
	bool operator()(const symbol<MAX_LEN, SENSITIVE>& _Left, const symbol<MAX_LEN, SENSITIVE>& _Right) const
	{	// apply operator< to operands
		return SENSITIVE 
			? _tcscmp(_Left.str, _Right.str) <= 0 
			: _tcsicmp(_Left.str, _Right.str) <= 0;
	}
};

}//namespace

#endif //__CR_SYMBOL_H__